package com.hospitalmanagementsystem.service.impl;

import com.hospitalmanagementsystem.dto.DoctorDTO;
import com.hospitalmanagementsystem.dto.UserDTO;
import com.hospitalmanagementsystem.entity.Department;
import com.hospitalmanagementsystem.entity.Doctor;
import com.hospitalmanagementsystem.entity.User;
import com.hospitalmanagementsystem.exception.ResourceNotFoundException;
import com.hospitalmanagementsystem.repository.DepartmentRepository;
import com.hospitalmanagementsystem.repository.DoctorRepository;
import com.hospitalmanagementsystem.repository.UserRepository;
import com.hospitalmanagementsystem.service.DoctorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class DoctorServiceImpl implements DoctorService {

    private final DoctorRepository doctorRepository;
    private final UserRepository userRepository;
    private final DepartmentRepository departmentRepository;

    @Autowired
    public DoctorServiceImpl(DoctorRepository doctorRepository, UserRepository userRepository, 
                           DepartmentRepository departmentRepository) {
        this.doctorRepository = doctorRepository;
        this.userRepository = userRepository;
        this.departmentRepository = departmentRepository;
    }

    @Override
    public List<DoctorDTO> getAllDoctors() {
        return doctorRepository.findAll().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public DoctorDTO getDoctorById(Long id) {
        Doctor doctor = doctorRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Doctor not found with id: " + id));
        return convertToDTO(doctor);
    }

    @Override
    @Transactional
    public DoctorDTO createDoctor(DoctorDTO doctorDTO) {
        Doctor doctor = convertToEntity(doctorDTO);
        Doctor savedDoctor = doctorRepository.save(doctor);
        return convertToDTO(savedDoctor);
    }

    @Override
    @Transactional
    public DoctorDTO updateDoctor(Long id, DoctorDTO doctorDTO) {
        Doctor doctor = doctorRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Doctor not found with id: " + id));
        
        // 更新医生信息
        if (doctorDTO.getUserId() != null && !doctorDTO.getUserId().equals(doctor.getUser().getId())) {
            User user = userRepository.findById(doctorDTO.getUserId())
                    .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + doctorDTO.getUserId()));
            doctor.setUser(user);
        }
        
        if (doctorDTO.getDepartmentId() != null) {
            Department department = departmentRepository.findById(doctorDTO.getDepartmentId())
                    .orElseThrow(() -> new ResourceNotFoundException("Department not found with id: " + doctorDTO.getDepartmentId()));
            doctor.setDepartment(department);
        }
        
        doctor.setSpecialization(doctorDTO.getSpecialization());
        doctor.setLicenseNumber(doctorDTO.getLicenseNumber());
        doctor.setBio(doctorDTO.getBio());
        doctor.setAvailableSlots(doctorDTO.getAvailableSlots());
        
        Doctor updatedDoctor = doctorRepository.save(doctor);
        return convertToDTO(updatedDoctor);
    }

    @Override
    @Transactional
    public void deleteDoctor(Long id) {
        if (!doctorRepository.existsById(id)) {
            throw new ResourceNotFoundException("Doctor not found with id: " + id);
        }
        doctorRepository.deleteById(id);
    }

    @Override
    public List<DoctorDTO> getDoctorsByDepartment(Long departmentId) {
        Department department = departmentRepository.findById(departmentId)
                .orElseThrow(() -> new ResourceNotFoundException("Department not found with id: " + departmentId));
        
        return doctorRepository.findByDepartment(department).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public DoctorDTO getDoctorByUserId(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId));
        
        Doctor doctor = doctorRepository.findByUser(user)
                .orElseThrow(() -> new ResourceNotFoundException("Doctor not found for user with id: " + userId));
        
        return convertToDTO(doctor);
    }

    private DoctorDTO convertToDTO(Doctor doctor) {
        DoctorDTO doctorDTO = new DoctorDTO();
        doctorDTO.setId(doctor.getId());
        
        if (doctor.getUser() != null) {
            UserDTO userDTO = new UserDTO();
            userDTO.setId(doctor.getUser().getId());
            userDTO.setUsername(doctor.getUser().getUsername());
            userDTO.setEmail(doctor.getUser().getEmail());
            userDTO.setFullName(doctor.getUser().getFullName());
            doctorDTO.setUser(userDTO);
            doctorDTO.setUserId(doctor.getUser().getId());
        }
        
        doctorDTO.setSpecialization(doctor.getSpecialization());
        
        if (doctor.getDepartment() != null) {
            doctorDTO.setDepartmentId(doctor.getDepartment().getId());
            doctorDTO.setDepartmentName(doctor.getDepartment().getName());
        }
        
        doctorDTO.setLicenseNumber(doctor.getLicenseNumber());
        doctorDTO.setBio(doctor.getBio());
        doctorDTO.setAvailableSlots(doctor.getAvailableSlots());
        doctorDTO.setCreatedAt(doctor.getCreatedAt());
        doctorDTO.setUpdatedAt(doctor.getUpdatedAt());
        
        return doctorDTO;
    }

    private Doctor convertToEntity(DoctorDTO doctorDTO) {
        Doctor doctor = new Doctor();
        
        if (doctorDTO.getId() != null) {
            doctor.setId(doctorDTO.getId());
        }
        
        if (doctorDTO.getUserId() != null) {
            User user = userRepository.findById(doctorDTO.getUserId())
                    .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + doctorDTO.getUserId()));
            doctor.setUser(user);
        }
        
        doctor.setSpecialization(doctorDTO.getSpecialization());
        
        if (doctorDTO.getDepartmentId() != null) {
            Department department = departmentRepository.findById(doctorDTO.getDepartmentId())
                    .orElseThrow(() -> new ResourceNotFoundException("Department not found with id: " + doctorDTO.getDepartmentId()));
            doctor.setDepartment(department);
        }
        
        doctor.setLicenseNumber(doctorDTO.getLicenseNumber());
        doctor.setBio(doctorDTO.getBio());
        doctor.setAvailableSlots(doctorDTO.getAvailableSlots());
        
        return doctor;
    }
} 